﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Media3D;
using ProjetoKinect.Model3d;
using ObjLoader.Loader.Loaders;
using System.IO;
using ObjLoader.Loader.Data.VertexData;
using ObjLoader.Loader.Data.Elements;
using System.Windows.Media;

namespace ProjetoKinect.Model
{
    class ParseObj
    {
        private LoadResult loadResult;
        private List<MyMash> mashList = new List<MyMash>();
        private List<TriangleObject> triangleObjectList = new List<TriangleObject>();
        private List<MyPoint3D> myPoint3DList;
        public float lessX = Int32.MaxValue;
        public float lessY = Int32.MaxValue;
        public float lessZ = Int32.MaxValue;
        public float biggerX = Int32.MinValue;
        public float biggerY = Int32.MinValue;
        public float biggerZ = Int32.MinValue;


        public ParseObj(string path)
        {
            ObjLoaderFactory objLoaderFactory = new ObjLoaderFactory();
            IObjLoader objLoader = objLoaderFactory.Create();
            FileStream fileStream = new FileStream(@path, FileMode.Open, FileAccess.Read);
            loadResult = objLoader.Load(fileStream);
            findMinAndMaxValues();
        }

        public void findMinAndMaxValues() {
            foreach (Vertex vertex in getVertexList())
            {
                if (vertex.X > biggerX)
                {
                    biggerX = vertex.X;
                }
                else if (vertex.X < lessX)
                {
                    lessX = vertex.X;
                }
                if (vertex.Y > biggerY)
                {
                    biggerY = vertex.Y;
                }
                else if (vertex.Y < lessY)
                {
                    lessY = vertex.Y;
                }
                if (vertex.Z > biggerZ)
                {
                    biggerZ = vertex.Z;
                }
                else if (vertex.Z < lessZ)
                {
                    lessZ = vertex.Z;
                }
            }
        }
        public IList<Vertex> getVertexList()
        {
            return loadResult.Vertices;
        }

        public List<MyPoint3D> getVertexListAsPoint3D()
        {
            if (myPoint3DList == null)
            {
                myPoint3DList = new List<MyPoint3D>();
                foreach (Vertex vertex in getVertexList())
                {
                  
                    myPoint3DList.Add(new MyPoint3D(vertex.X, vertex.Y, vertex.Z));
                }
            }
            return myPoint3DList;
        }

        public List<MyMash> getFacesList()
        {
            Group group = loadResult.Groups[0];
           
            IList<Face> faces = group.Faces;
            IList<Normal> normals = loadResult.Normals;
          
            for (int i = 0; i < faces.Count; i++)
            {
                IList<int> facesVertexIndex = new List<int>();
                for (int j = 0; j < faces[i].Count; j++)
                {
                    int vertexIndex = faces[i][j].VertexIndex - 1;
                    facesVertexIndex.Add(vertexIndex);
                }

                for (int k = 1; k < facesVertexIndex.Count - 1; k++)
                {
                   // MyPoint3D normal = new MyPoint3D(normals[i].X, normals[i].Y, normals[i].Z);
                    mashList.Add(new MyMash(facesVertexIndex[0], facesVertexIndex[k], facesVertexIndex[k +1],getNormals(i)));
                }

            }
            return mashList;
        }

        public MyPoint3D getNormals(int i) {
           Normal normal = loadResult.Normals[i];
           return new MyPoint3D(normal.X,normal.Y,normal.Z);
        }
        internal List<MyTriangle> getTriangles()
        {
            List<MyTriangle> trianglesList = new List<MyTriangle>();

            List<MyMash> facesList = new List<MyMash>();

           facesList.AddRange(getFacesList());
            
            List<MyPoint3D> vertexList = getVertexListAsPoint3D();

            MyPoint3D myPoint1;
            MyPoint3D myPoint2;
            MyPoint3D myPoint3;

            for (int i = 0;i<facesList.Count;i++)
            {
                MyMash myMash = facesList[i];
                myPoint1 = vertexList[myMash.getVertexIndex1()];
                myPoint2 = vertexList[myMash.getVertexIndex2()];
                myPoint3 = vertexList[myMash.getVertexIndex3()];

                trianglesList.Add(new MyTriangle(myPoint1, myPoint2, myPoint3,getNormals(i)));
            }

            return trianglesList;
        }

        internal List<TriangleObject> getTriangleObjects(Color color,MyPoint3D boundBoxPoint)
        {         
            List<MyMash> facesList = new List<MyMash>();

            List<TriangleObject> TriangleObjectList = new List<TriangleObject>();
            MyPoint3D myPoint1;
            MyPoint3D myPoint2;
            MyPoint3D myPoint3;

            List<MyPoint3D> vertexList = getVertexListAsPoint3D();
           
         
                TriangleObject triangleObject = new TriangleObject();
                if (loadResult.Materials.Count > 0) {
                    double opacity = loadResult.Materials[0].Transparency;
                    triangleObject.setTransparency(opacity);
                }
                triangleObject.setColor(color);
                foreach (MyMash myMash in getFacesList())
                {
                    myPoint1 = vertexList[myMash.getVertexIndex1()].subtraction(boundBoxPoint);
                    myPoint2 = vertexList[myMash.getVertexIndex2()].subtraction(boundBoxPoint);
                    myPoint3 = vertexList[myMash.getVertexIndex3()].subtraction(boundBoxPoint);

                    triangleObject.addTriangle(new MyTriangle(myPoint1, myPoint2, myPoint3,myMash.getNormal()));
                }
                TriangleObjectList.Add(triangleObject);
            

            return TriangleObjectList;
        }
    }
}
